package com.taobao.demo.user.security;

import com.taobao.demo.user.entity.User;
import com.taobao.demo.user.service.IUserService;
import com.taobao.demo.user.utils.JwtUtil;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;

/**
 * JWT认证拦截器（每次请求都经过此过滤器，解析Token并设置认证信息）
 * @author 83776
 */
@Component
public class JwtAuthFilter extends OncePerRequestFilter {

    @Resource
    private JwtUtil jwtUtil; // 注入JWT工具类

    @Resource
    private IUserService userService; // 注入用户服务（用于查询用户）

    @Override
    protected void doFilterInternal(
            HttpServletRequest request,
            HttpServletResponse response,
            FilterChain filterChain
    ) throws ServletException, IOException {

        // 1. 从请求头获取Token（格式：Bearer {token}）
        String authHeader = request.getHeader("Authorization");
        String token = null;
        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            token = authHeader.substring(7); // 截取"Bearer "后面的Token
        }

        // 2. 如果Token存在且未设置认证信息，则解析Token
        if (token != null && SecurityContextHolder.getContext().getAuthentication() == null) {

            // 3. 验证Token有效性
            if (jwtUtil.validateToken(token)) {

                // 4. 从Token中解析用户ID和角色
                Long userId = jwtUtil.getUserIdFromToken(token);
                String role = jwtUtil.getRoleFromToken(token);

                // 5. 查询用户（确保用户存在且状态正常）
                User user = userService.getById(userId);
                if (user != null) {

                    // 6. 构建Spring Security需要的用户权限信息
                    // 注意：角色必须以"ROLE_"为前缀，否则@PreAuthorize("hasRole('ADMIN')")会失效
                    UserDetails userDetails = new org.springframework.security.core.userdetails.User(
                            user.getUsername(),
                            user.getPassword(), // 密码可为空（此处仅用于认证标记，不实际校验）
                            Collections.singletonList(new SimpleGrantedAuthority("ROLE_" + role))
                    );

                    // 7. 创建认证对象并设置到Security上下文
                    UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
                            userDetails,
                            null, // 凭证（密码）可为空，已通过Token验证
                            userDetails.getAuthorities() // 权限列表
                    );
                    // 设置请求详情（如IP）
                    authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                    // 将认证信息存入上下文，后续接口可通过SecurityContext获取用户信息
                    SecurityContextHolder.getContext().setAuthentication(authToken);
                }
            }
        }

        // 8. 继续执行过滤链（无论是否认证，都让请求继续处理）
        filterChain.doFilter(request, response);
    }
}
